<?php


namespace services\patient;

use api\modules\mini\forms\patient\PatientForm;
use api\modules\mini\forms\patient\PatientOrderForm;
use common\components\Service;
use common\helpers\DateHelper;
use common\helpers\RedisHelper;
use common\models\base\TreatmentProject;
use common\models\patient\Patient;
use common\models\patient\PatientOrder;
use common\models\patient\PatientType;
use common\models\spoker\Spoker;
use services\base\TreatmentProjectService;
use services\shop\ShopService;
use Yii;
use yii\db\Expression;

class PatientOrderService extends Service
{
    /**
     * 预约列表
     * @param array $params
     * @param int $page
     * @param int $pageSize
     * @return array
     */
    public function getListPage(array $params = [], int $page = 0, int $pageSize = 0): array
    {
        $query = PatientOrder::find()->alias('po')
            ->select([
                'po.id order_id', 'po.order_time', 'po.shop_id', 'po.treatment_project_id',
                'p.id', 'p.name', 'p.type_id', 'p.created_at',
            ])
            ->innerJoin(Patient::tableName().' p', 'p.id = po.patient_id')
            ->where([
                'p.user_id' => Yii::$app->user->identity->member_id,
                'p.status' => Patient::STATUS_ENABLE
            ]);
        if (isset($params['name']) && $params['name']) {
            $query->andWhere(['like', 'p.name', $params['name']]);
        }
        // 排序
        $order = [
            'po.order_time' => SORT_DESC,
            'po.id' => SORT_DESC,
        ];

        return $this->getListPageRes($query, $page, $pageSize, $order);
    }

    /**
     * 格式化列表
     * @param array $data
     * @return array
     */
    public function getListPageFormat(array $data = []): array
    {
        $list = [];
        foreach ($data as $row) {
            $treatmentProject = RedisHelper::getTreatmentProject($row['treatment_project_id']);
            $patientType = RedisHelper::getPatientType($row['type_id']);
            $list[] = [
                'id' => $row['id'],
                'order_id' => $row['order_id'],
                'shop_name' => RedisHelper::getShop($row['shop_id'])->name ?? '',
                'name' => $row['name'],
                'treatment_project' => $treatmentProject ? $treatmentProject->name : '',
                'type_str' => $patientType && $patientType->status != PatientType::STATUS_DELETE ? $patientType->name : '',
                'created_at_str' => DateHelper::timestampToDate($row['created_at'], DateHelper::DATE_FORMAT_1),
                'order_time_str' => DateHelper::timestampToDate($row['order_time'], DateHelper::DATE_FORMAT_1),
            ];
        }
        return $list;
    }

    /**
     * 预约信息
     * @param int $id
     * @return array
     */
    public function getEditInfo(int $id): array
    {
        $data = [];
        $patientOrder = PatientOrder::findOne($id);
        if ($patientOrder) {
            $data = [
                'id' => $patientOrder->id,
                'order_time' => DateHelper::timestampToDate($patientOrder->order_time, DateHelper::DATE_FORMAT_4),
                'shop_id' => $patientOrder->shop_id,
                'shop_name' => RedisHelper::getShop($patientOrder->shop_id)->name ?? '',
                'treatment_project_id' => $patientOrder->treatment_project_id,
                'treatment_project_name' => RedisHelper::getTreatmentProject($patientOrder->treatment_project_id)->name ?? '',
                'remark' => $patientOrder->remark,
            ];
        }
        $condition = [
            'treatment_project' => TreatmentProjectService::getEditCondition($data['treatment_project_id'] ?? null),
            'shop' => ShopService::getEditCondition($data['shop_id'] ?? null),
        ];
        if ($patientOrder) {
            if (in_array($data['treatment_project_id'], array_column($condition['treatment_project'], 'value')) === false) {
                $data['treatment_project_id'] = 0;
            }
            if (in_array($data['shop_id'], array_column($condition['shop'], 'value')) === false) {
                $data['shop_id'] = 0;
            }
        }
        return array_merge($data, ['condition' => $condition]);
    }

    /**
     * 预约是否过期
     * @param int $orderTime
     * @return bool
     */
    public static function isExpired(int $orderTime): bool
    {
        $today = DateHelper::today();
        return $orderTime < $today['start'] ? true : false;
    }

    /**
     * 患者最近一次预约记录
     * @param int|array $ids
     * @return PatientOrder[]
     */
    public static function getPatientOrderMap($ids): array
    {
        return PatientOrder::find()
            ->where(['id' => $ids])
            ->indexBy('patient_id')
            ->all();
    }

    /**
     * 新增预约记录
     * @param Patient $patient
     * @param PatientForm $model
     * @return PatientOrder
     */
    public static function createOrder(Patient $patient, PatientForm $model): PatientOrder
    {
        $patientOrder = new PatientOrder();
        $patientOrder->patient_id = $patient->id;
        $patientOrder->order_time = strtotime($model->order_time);
        $patientOrder->shop_id = $model->shop_id ?: 0;
        $patientOrder->treatment_project_id = $model->treatment_project_id ?: 0;
        $patientOrder->status = PatientOrder::STATUS_WAIT;
        $patientOrder->saveAndCheckResult();

        return $patientOrder;
    }

    public static function editModel(PatientOrder $patientOrder, PatientOrderForm $model): PatientOrder
    {
        $patientOrder->patient_id = $model->patient_id;
        $patientOrder->order_time = strtotime($model->order_time);
        $patientOrder->shop_id = $model->shop_id;
        $patientOrder->treatment_project_id = $model->treatment_project_id;
        $patientOrder->remark = $model->remark;
        $patientOrder->status = PatientOrder::STATUS_WAIT;
        $patientOrder->saveAndCheckResult();

        return $patientOrder;
    }

    /**
     * 新增预约
     * @param PatientOrderForm $model
     * @return void
     * @throws \Exception
     */
    public static function create(PatientOrderForm $model): void
    {
        try {
            $transaction = Yii::$app->db->beginTransaction();

            // 1.新增预约记录
            $patientOrder = new PatientOrder();
            $patientOrder = self::editModel($patientOrder, $model);

            // 2.更新最后一次预约ID
            $patient = $model->getPatient();
            $patient->last_order_id = $patientOrder->id;
            $patient->saveAndCheckResult();

            $transaction->commit();
        } catch (\Exception $e) {
            $transaction->rollBack();
            throw $e;
        }
    }

    /**
     * 编辑预约
     * @param PatientOrderForm $model
     * @return void
     * @throws \Exception
     */
    public static function update(PatientOrderForm $model): void
    {
        try {
//            $transaction = Yii::$app->db->beginTransaction();

            // 1.更新预约记录
            $patientOrder = $model->getPatientOrder();
            $patientOrder = self::editModel($patientOrder, $model);

//            $transaction->commit();
        } catch (\Exception $e) {
//            $transaction->rollBack();
            throw $e;
        }
    }

    /**
     * pc预约列表
     *
     * @param array $params
     * @param int $page
     * @param int $pageSize
     * @return array
     */
    public function patientOrderList(array $params = [], int $page = 0, int $pageSize = 0): array
    {
        $query = PatientOrder::find()->alias('po')
            ->select([
                'po.id order_id', 'po.order_time', 'po.shop_id', 'po.treatment_project_id', 'p.status',
                'p.id', 'p.name', 'p.type_id', 'p.created_at',
                's.name spoker_name'
            ])
            ->innerJoin(Patient::tableName().' p', 'p.id = po.patient_id')
            ->innerJoin(Spoker::tableName().' s', 's.id = p.spoker_id')
            ->where([
                'p.status' => Patient::STATUS_ENABLE
            ]);
        // 开始时间
        if (isset($params['order_stime']) && $params['order_stime']) {
            $query->andWhere(['>=', 'po.order_time', strtotime($params['order_stime'])]);
        }
        // 结束时间
        if (isset($params['order_etime']) && $params['order_etime']) {
            $query->andWhere(['<=', 'po.order_time', strtotime($params['order_etime'] . ' 23:59:59')]);
        }
        if (isset($params['spoker_id']) && $params['spoker_id']) {
            $query->andWhere(['p.spoker_id' => $params['spoker_id']]);
        }
        if (isset($params['shop_id']) && $params['shop_id']) {
            $query->andWhere(['po.shop_id' => $params['shop_id']]);
        }
        if (isset($params['status']) && $params['status']) {
            $query->andWhere(['po.status' => $params['status']]);
        }
        // 排序
        $order = [
            'po.order_time' => SORT_DESC,
            'po.id' => SORT_DESC,
        ];

        $list = $this->getListPageRes($query, $page, $pageSize, $order);
        foreach ($list['list'] as &$val) {
            $treatmentProject = RedisHelper::getTreatmentProject($val['treatment_project_id']);
            $patientType = RedisHelper::getPatientType($val['type_id']);
            $val['status_name'] = PatientOrder::$statuss[$val['status']] ?? '';
            $val['shop_name'] =  RedisHelper::getShop($val['shop_id'])->name ?? '';
            $val['treatment_project'] = $treatmentProject && $treatmentProject->status != TreatmentProject::STATUS_DELETE ? $treatmentProject->name : '';
            $val['type_str'] = $patientType && $patientType->status != PatientType::STATUS_DELETE ? $patientType->name : '';
            $val['created_at_str'] = DateHelper::timestampToDate($val['created_at'], DateHelper::DATE_FORMAT_1);
            $val['order_time_str'] = DateHelper::timestampToDate($val['order_time'], DateHelper::DATE_FORMAT_1);
        }
        return $list;
    }

    /**
     * 状态下拉筛选项
     * @return array[]
     */
    public static function getStatusCondition(): array
    {
        return [
            ['value' => PatientOrder::STATUS_WAIT, 'label' => PatientOrder::$statuss[PatientOrder::STATUS_WAIT]],
            ['value' => PatientOrder::STATUS_ARRIVE, 'label' => PatientOrder::$statuss[PatientOrder::STATUS_ARRIVE]],
            ['value' => PatientOrder::STATUS_EXPIRED, 'label' => PatientOrder::$statuss[PatientOrder::STATUS_EXPIRED]],
        ];
    }

    /**
     * 患者详情消费预约query
     * @param int $patientId
     * @return \yii\db\ActiveQuery
     */
    public static function getPatientOrderDetailQuery(int $patientId)
    {
        $query = PatientOrder::find()
            ->select(['id', 'order_time sort_time', new Expression("2 type")])
            ->where([
                'patient_id' => $patientId,
            ]);
        return $query;
    }

    /**
     * 患者详情预约记录
     * @param int|array $ids
     * @return array
     */
    public static function getPatientDetailOrderMap(int|array $ids): array
    {
        $query = PatientOrder::find()->alias('po')
            ->select([
                'po.id', 'po.order_time', 'po.shop_id', 'po.treatment_project_id', 'po.remark',
//                'p.id', 'p.name', 'p.type_id', 'p.created_at',
            ])
//            ->innerJoin(Patient::tableName().' p', 'p.id = po.patient_id')
            ->where([
                'po.id' => $ids,
            ]);
        $data = $query->asArray()->all();
        $dataFormat = [];
        foreach ($data as $row) {
            $treatmentProject = RedisHelper::getTreatmentProject($row['treatment_project_id']);
            $dataFormat[$row['id']] = [
                'remark' => $row['remark'],
                'shop_name' => RedisHelper::getShop($row['shop_id'])->name ?? '',
                'treatment_project' => $treatmentProject ? $treatmentProject->name : '',
                'created_at_str' => DateHelper::timestampToDate($row['order_time'], DateHelper::DATE_FORMAT_4),
            ];
        }
        return $dataFormat;
    }
}
